// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module ADR_fub
  (
    input      iClk, //input clock signal
    input      iRst_n, //input reset signal (active low)
	  input      [3:0]rstatus,
    input      FM_ADR_MODE0,
    input      iFM_ADR_COMPLETE_PLD,
    input      iFM_CPU0_ADR_EXT_TRIGGER_N,
    input      iFM_GLOBAL_RESET,
	input      iPS_EN,
    input      iPWRGD_PS_PWROK,

    output  reg   oFM_CPU0_ADR_TRIGGER_N,
    output     [31:0] ADRcounter1,
    output     [31:0] ADRcounter2
   );


//////////////////////////////////////////////////////////////////////////////////
// Parameters
//////////////////////////////////////////////////////////////////////////////////
  localparam  LOW =1'b0;
  localparam  HIGH=1'b1;
  
  localparam ST_PLATFORM_ON        = 4'd8;   //param from master_fub

//////////////////////////////////////////////////////////////////////////////////
// Internal signals declaration
//////////////////////////////////////////////////////////////////////////////////
  reg    rPWRGD_PS_PWROK_FF;
  reg    rPSU_FAULT_FF;
  reg    rFM_GLOBAL_RESET_FF;
  reg    rFM_CPU0_ADR_EXT_TRIGGER_N_FF;
  reg    rADR_TRIGGER_START;
  reg    rADR_COMPLETE;
  reg	   rADR_COMPLETE_POSEDGE;
  reg    rADR_COUNTER_Indication;	// This register assert at rADR_COMLETE posedge, and de-assert when Global Reset.

 
always @(posedge iClk or negedge iRst_n) begin
  if(!iRst_n) begin   
    rPWRGD_PS_PWROK_FF               <= LOW;
    rPSU_FAULT_FF                    <= LOW;
		rFM_GLOBAL_RESET_FF              <= LOW;
    rFM_CPU0_ADR_EXT_TRIGGER_N_FF    <= HIGH;
    rADR_TRIGGER_START               <= LOW;
    rADR_COMPLETE                    <= LOW;
    rADR_COMPLETE_POSEDGE            <= LOW;
    rADR_COUNTER_Indication          <= LOW;

   end
	else if(!FM_ADR_MODE0) begin
	  rPWRGD_PS_PWROK_FF               <= LOW;
    rPSU_FAULT_FF                    <= LOW;
		rFM_GLOBAL_RESET_FF              <= LOW;
    rFM_CPU0_ADR_EXT_TRIGGER_N_FF    <= HIGH;
    rADR_TRIGGER_START               <= LOW;
		rADR_COMPLETE                    <= LOW;
    rADR_COMPLETE_POSEDGE            <= LOW;
    rADR_COUNTER_Indication          <= LOW;		
	end
  else begin
    rPWRGD_PS_PWROK_FF               <= iPWRGD_PS_PWROK;
    rPSU_FAULT_FF                    <= (iPS_EN && (rPWRGD_PS_PWROK_FF && !iPWRGD_PS_PWROK))  ? HIGH : rPSU_FAULT_FF;     //PS_EN is on and PS_PWRGD is down
    rFM_GLOBAL_RESET_FF              <= iFM_GLOBAL_RESET;
    rFM_CPU0_ADR_EXT_TRIGGER_N_FF    <= iFM_CPU0_ADR_EXT_TRIGGER_N;
   
    rADR_TRIGGER_START               <= (!iFM_CPU0_ADR_EXT_TRIGGER_N &&(rstatus == ST_PLATFORM_ON))?HIGH :rADR_TRIGGER_START;
	  rADR_COMPLETE                    <= (iFM_ADR_COMPLETE_PLD &&(rstatus == ST_PLATFORM_ON))? HIGH:rADR_COMPLETE;
        rADR_COMPLETE_POSEDGE            <= (!rADR_COMPLETE && (iFM_ADR_COMPLETE_PLD && (rstatus == ST_PLATFORM_ON))) ? HIGH : LOW;
    if (rADR_COMPLETE_POSEDGE)
        rADR_COUNTER_Indication         <= HIGH;
    else if (!iFM_GLOBAL_RESET && rFM_GLOBAL_RESET_FF)
        rADR_COUNTER_Indication         <= LOW;
  end
  
end
//////////////////////////////////////////////////////////////////////////////////
// ADR TRIGGERRED BY FPGA
////////////////////////////////////////////////////////////////////////////////// 
always @(posedge iClk or negedge iRst_n) begin
  if(!iRst_n) begin
    oFM_CPU0_ADR_TRIGGER_N               <= HIGH;
 
  end
  else if (!FM_ADR_MODE0) begin
    oFM_CPU0_ADR_TRIGGER_N               <= HIGH;

  end
  else if (rPSU_FAULT_FF || !rFM_CPU0_ADR_EXT_TRIGGER_N_FF) begin
    oFM_CPU0_ADR_TRIGGER_N               <= LOW;
  end
end
//////////////////////////////////////////////////////////////////////////////////
// COUNTER NEED TO BE LOGGED
////////////////////////////////////////////////////////////////////////////////// 
ADRcounter ADRcounter_U1(

      .iClk(iClk),
      .iRst_n(iRst_n),
      .iStart(rADR_TRIGGER_START),
      .iStop(rADR_COMPLETE),
      .ovCnt(ADRcounter1)

  );
  
 ADRcounter ADRcounter_U2(

      .iClk(iClk),
      .iRst_n(iRst_n),
      .iStart(rADR_COUNTER_Indication),
      .iStop(!iFM_GLOBAL_RESET && rFM_GLOBAL_RESET_FF),
      .ovCnt(ADRcounter2)

  );
   
  endmodule